package lljson

import (
	"reflect"
	"strconv"
	"strings"
)

type BeginSerialize struct {
	structIf bool
	s        string
}

// Serialize 序列化入口
func Serialize(v interface{}) string {
	b := new(BeginSerialize)
	b.GetIT(v)
	replace := strings.Replace(b.s, "[]", "null", -1)
	return replace
}

// GetIT 用到这个了，说明开始了一个结构体的
func (b *BeginSerialize) GetIT(v interface{}) {
	b.s = b.s + "{"
	typeOf := reflect.TypeOf(v)
	valOf := reflect.ValueOf(v)

	for i := 0; i < typeOf.NumField(); i++ {
		inFieldType := typeOf.Field(i)
		inFieldValue := valOf.Field(i)

		Sname := inFieldType.Tag.Get("json")
		if Sname == "" {
			Sname = inFieldType.Name
		}

		fieldType := fieldType(inFieldValue)

		switch fieldType {

		case reflect.Struct:
			// 先加个名字
			b.s = b.s + AddQuotationMarks(inFieldType.Name) + ":"
			b.GetIT(inFieldValue.Interface())

		case reflect.Map:

			b.s = b.s + AddQuotationMarks(inFieldType.Name) + ":"

		case reflect.Slice:
			//temp := 0 // 用于鉴定是不是第一个切片

			if ArrayType(valOf.Field(i).Interface()) { // 是否为定义上的底层切片(非结构体切片)
				b.s = b.s + AddQuotationMarks(inFieldType.Name) + ":["

				b.HandleBottomArray(valOf.Field(i).Interface())

			} else { //这里表示是结构体
				sliceLen := inFieldValue.Len()

				b.s = b.s + AddQuotationMarks(inFieldType.Name) + ":["

				for ii := 0; ii < sliceLen; ii++ {
					if inFieldValue.Index(ii).Kind() == reflect.Ptr {
						b.GetIT(inFieldValue.Index(ii).Elem().Interface())
					} else {
						b.GetIT(inFieldValue.Index(ii).Interface())
					}

					b.s = AddComma(b.s)
				}
			}
			b.s = DeleteAComma(b.s)
			b.s = b.s + "]"
		//temp++
		case reflect.Ptr:
			if inFieldValue.IsNil() {
				b.s = b.s + AddQuotationMarks(inFieldType.Name) + ":null"
			} else {
				b.s = b.s + AddQuotationMarks(inFieldType.Name) + ":"
				b.GetIT(inFieldValue.Elem().Interface())
			}

		default:
			b.s = b.s + AddQuotationMarks(Sname) + ":" + ToString(inFieldValue.Interface())
		}

		if i != typeOf.NumField()-1 {
			b.s = AddComma(b.s)
		}

	}
	b.s = AddBraceRight(b.s)
}

// 返回是什么类型的值，详见reflect.Kind
func fieldType(v reflect.Value) reflect.Kind {
	return v.Kind()
}

func (b *BeginSerialize) HandleBottomArray(v interface{}) {
	switch v.(type) {

	case []uint:
		for _, val := range reflect.ValueOf(v).Interface().([]uint) {
			b.s = b.s + strconv.Itoa(int(val)) + ","
		}

	case []int:
		for _, val := range reflect.ValueOf(v).Interface().([]int) {
			b.s = b.s + strconv.Itoa(val) + ","
		}

	case []uint8:
		for _, val := range reflect.ValueOf(v).Interface().([]uint8) {
			b.s = b.s + strconv.Itoa(int(val)) + ","
		}

	case []uint16:
		for _, val := range reflect.ValueOf(v).Interface().([]uint16) {
			b.s = b.s + strconv.Itoa(int(val)) + ","
		}

	case []float64:
		for _, val := range reflect.ValueOf(v).Interface().([]float64) {
			b.s = b.s + strconv.FormatFloat(val, 'f', -1, 64) + ","
		}

	case []bool:
		for _, val := range reflect.ValueOf(v).Interface().([]bool) {
			if val == true {
				b.s = b.s + "true" + ","
			} else {
				b.s = b.s + "false" + ","
			}
		}

	}
}
